package org.celery.client.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.celery.client.service.ClientOrderService;
import org.celery.common.utils.IPUtil;
import org.celery.modules.goods.service.IGoodsService;
import org.celery.modules.order.entity.Order;
import org.celery.modules.order.enums.*;
import org.celery.modules.order.service.IOrderService;
import org.celery.modules.order.vo.OrderVO;
import org.celery.modules.order.wrapper.OrderWrapper;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.SpringUtil;
import org.springblade.modules.system.entity.Param;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.enums.UserStatusEnum;
import org.springblade.modules.system.service.IParamService;
import org.springblade.modules.system.service.IUserService;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("order")
@Api(value = "订单")
public class ClientOrderController {

    private final ClientOrderService clientOrderService;
    private final IOrderService orderService;
    private final IGoodsService goodsService;
    private final IParamService paramService;

    /**
     * 订单提交
     */
    @PostMapping("/submit")
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "订单提交")
    public R<Order> submit(@RequestBody Order order, HttpServletRequest request) {
        Param limitOrderTime = paramService.getOne(Wrappers.<Param>lambdaQuery()
                .eq(Param::getParamKey, "limit_order_time")
        );
        int limitOrderTimeInt = Func.isEmpty(limitOrderTime) ? 16 : Integer.parseInt(limitOrderTime.getParamValue());

        LocalDate now = LocalDate.now();

        if (now.isAfter(order.getTime())) {
            return R.fail("预约时间不能晚于当前时间");
        }

        if (now.getDayOfYear() == order.getTime().getDayOfYear()) {
            return R.fail("请至少提前一天预约");
        }

        if (order.getTime().plusDays(-1).getDayOfYear() == now.getDayOfYear() && LocalDateTime.now().getHour() >= limitOrderTimeInt) {
            return R.fail("预约必须在预约前一日的" + limitOrderTimeInt + ":00之前");
        }

        if (Math.abs(DateUtil.between(order.getTime(), now).getDays()) > 1) {
            return R.fail("请提前一天预约");
        }

        synchronized (this) {
            BigDecimal goodsAmount = clientOrderService.computeTotalAmount(order.getAssociatedGoods());
            BigDecimal logisticsFee = clientOrderService.computeLogisticsFee(order.getShippingAddress(), request.getServerName());
            order.setGoodsAmountTotal(goodsAmount);
            order.setLogisticsFee(logisticsFee);
            order.setTotalAmount(goodsAmount.add(logisticsFee));
            order.setGoodsCount(clientOrderService.computeCount(order.getAssociatedGoods()));
            order.setPayChannel(PayChannelEnum.CASH_ON_DELIVERY.getStatus());
            order.setPayStatus(OrderStatusPayEnum.PENDING.getStatus());
            order.setStatus(OrderStatusEnum.NORMAL.getStatus());
            order.setShipStatus(OrderStatusShipEnum.TO_BE_CONFIRM.getStatus());

            String ip = IPUtil.getIpAddr(request);
            String ipAndArea = IPUtil.getCityInfo(ip);

            order.setFromDomain(request.getServerName());
            if (Func.isEmpty(ipAndArea)) {
                order.setFromIp(ip);
            } else {
                order.setFromIp(ipAndArea + "-" + ip);
            }
            // 默认为1 => 台湾 TODO - 后续需要做多地区
            order.setArea(1);

            Long businessId = clientOrderService.computeGoodsBusinessId(order.getAssociatedGoods());
            order.setFromUser(businessId);

            List<User> businessList = SpringUtil.getBean(IUserService.class).list(Wrappers.<User>lambdaQuery()
                    .eq(User::getStatus, UserStatusEnum.NORMAL.getStatus())
                    .eq(User::getId, businessId)
            );
            if (Func.isNotEmpty(businessList)) {
                if (Func.isNotEmpty(businessList.get(0).getAddress())) {
                    order.setShippingAddress(businessList.get(0).getAddress());
                }
            }

            order.setCode(orderService.getOrderCode());

            // 获取历史订单量
            QueryWrapper<Order> historyCountQueryWrapper = new QueryWrapper<>();
            historyCountQueryWrapper.lambda().eq(Order::getFromDomain, request.getServerName())
                    .eq(Order::getReceiverPhone, order.getReceiverPhone())
                    .or().eq(Order::getFromIp, ip);
            if (Func.isNotEmpty(order.getReceiverEmail())) {
                historyCountQueryWrapper.lambda().or().eq(Order::getReceiverEmail, order.getReceiverEmail());
            }
            int historyCount = orderService.count(historyCountQueryWrapper);

            order.setIsNew(historyCount == 0 ? OrderIsNewEnum.NEW.getType() : OrderIsNewEnum.OLD.getType());

            if (!orderService.save(order)) {
                throw new ServiceException("创建订单失败!");
            }

            // 修改商品销量
            goodsService.addSell(order);
        }

        return R.data(order);
    }

    /**
     * 订单详情
     */
    @GetMapping("/detail")
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "订单详情")
    public R<OrderVO> detail(String orderId) {
        Order order = orderService.getById(orderId);
        return R.data(Func.isEmpty(order) ? null : OrderWrapper.build().entityVO(order));
    }

    /**
     * 运费计算
     */
    @PostMapping("/compute-logistics-fee")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "运费计算")
    public R<BigDecimal> computeLogisticsFee(@RequestParam("address") String address, HttpServletRequest request) {
        return R.data(clientOrderService.computeLogisticsFee(address, request.getServerName()));
    }

    /**
     * 订单列表
     */
    @GetMapping("/list")
    @ApiOperationSupport(order = 4)
    @ApiOperation(value = "订单列表")
    public R<IPage<OrderVO>> list(Order order, Query query, @RequestParam(required = false) String goodName, BladeUser bladeUser) {
        QueryWrapper<Order> queryWrapper = Condition.getQueryWrapper(order);
        queryWrapper.lambda().orderByAsc(Order::getShipStatus).orderByDesc(Order::getCreateTime);
        if (Func.isNotEmpty(order.getReceiverName())) {
            queryWrapper.lambda().like(Order::getReceiverName, order.getReceiverName());
            order.setReceiverName(null);
        }
        if (Func.isNotEmpty(order.getReceiverPhone())) {
            queryWrapper.lambda().like(Order::getReceiverPhone, order.getReceiverPhone());
            order.setReceiverPhone(null);
        }

        if (Func.isNotEmpty(goodName)) {
            queryWrapper.lambda().like(Order::getAssociatedGoods, goodName);
        }
        queryWrapper.lambda().eq(Order::getCreateUser, bladeUser.getUserId()).orderByDesc(Order::getCreateTime);

        IPage<Order> pages = orderService.page(Condition.getPage(query), queryWrapper);
        return R.data(OrderWrapper.build().pageVO(pages));
    }

    /**
     * 订单详情
     */
    @PostMapping("/cancel")
    @ApiOperationSupport(order = 5)
    @ApiOperation(value = "订单详情")
    public R<Boolean> cancel(String orderId) {
        Order order = orderService.getById(orderId);
        if (Func.isEmpty(order)) {
            return R.fail("预约不存在!");
        }
        if (order.getShipStatus() == OrderStatusShipEnum.COMPLETED.getStatus()) {
            return R.fail("预约已完成, 无法取消!");
        }
        if (order.getStatus() == OrderStatusEnum.VOID.getStatus()) {
            return R.fail("预约已取消, 请勿重复取消!");
        }

        LocalDateTime now = LocalDateTime.now();

        if (now.getDayOfYear() == order.getTime().getDayOfYear()) {
            return R.fail("请至少提前一天取消预约");
        }

        Param limitOrderTime = paramService.getOne(Wrappers.<Param>lambdaQuery()
                .eq(Param::getParamKey, "limit_order_time")
        );
        int limitOrderTimeInt = Func.isEmpty(limitOrderTime) ? 16 : Integer.parseInt(limitOrderTime.getParamValue());
        if (order.getTime().plusDays(-1).getDayOfYear() == now.getDayOfYear() && LocalDateTime.now().getHour() >= limitOrderTimeInt) {
            return R.fail("预约必须在预约前一日的" + limitOrderTimeInt + ":00之前");
        }

         order.setShipStatus(OrderStatusShipEnum.RETURNED.getStatus());

        return R.data(orderService.updateById(order));
    }

    /**
     * 商户订单列表
     */
    @GetMapping("/merchant-order-list")
    @ApiOperationSupport(order = 6)
    @ApiOperation(value = "商户订单列表")
    public R<IPage<OrderVO>> merchantOrderList(Order order, Query query, @RequestParam(required = false) String goodName, BladeUser bladeUser) {
        QueryWrapper<Order> queryWrapper = Condition.getQueryWrapper(order);
        queryWrapper.lambda().orderByAsc(Order::getShipStatus).orderByDesc(Order::getCreateTime);
        if (Func.isNotEmpty(order.getReceiverName())) {
            queryWrapper.lambda().like(Order::getReceiverName, order.getReceiverName());
            order.setReceiverName(null);
        }
        if (Func.isNotEmpty(order.getReceiverPhone())) {
            queryWrapper.lambda().like(Order::getReceiverPhone, order.getReceiverPhone());
            order.setReceiverPhone(null);
        }

        if (Func.isNotEmpty(goodName)) {
            queryWrapper.lambda().like(Order::getAssociatedGoods, goodName);
        }
        queryWrapper.lambda().eq(Order::getFromUser, bladeUser.getUserId()).orderByDesc(Order::getCreateTime);

        IPage<Order> pages = orderService.page(Condition.getPage(query), queryWrapper);
        return R.data(OrderWrapper.build().pageVO(pages));
    }

    /**
     * 订单状态修改
     */
    @PostMapping("/status-change")
    @ApiOperationSupport(order = 7)
    @ApiOperation(value = "订单详情")
    public R<Boolean> statusChange(String orderId, Integer status) {
        Order order = orderService.getById(orderId);
        if (Func.isEmpty(order)) {
            return R.fail("预约不存在!");
        }

//        LocalDateTime now = LocalDateTime.now();

//        if (now.getDayOfYear() == order.getTime().getDayOfYear()) {
//            return R.fail("请至少提前一天取消预约");
//        }

        order.setShipStatus(status);

        return R.data(orderService.updateById(order));
    }
}
